/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.inspur.edp.lcm.metadata.common.util.process;

import com.inspur.edp.lcm.metadata.common.FileServiceImp;
import com.inspur.edp.lcm.metadata.common.Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class UnixProcessUtil extends AbstractProcessUtil {

    public String killByPidCmd = "kill -9 ";

    protected String open = "/usr/bin/open ";

    public String START_CMD = "startup.sh";

    public String START_CMD_OLD = "startup-linux.sh";

    public String START_CMD_DEBUGGER = ".startup-debugger-linux.sh";

    public String cmdPrefix = "/bin/sh -c ";

    protected String getPidsByPortCmd = "lsof -i:";

    protected String getJavaProcessesCmd = "ps -aux | grep java";

    // 根据Pid将杀死进程
    @Override
    public void killProcessByPid(int pid) {
        execFast(killByPidCmd + pid);
    }

    @Override
    public void open(String path) {
        execFast(open + path);
    }

    @Override
    public List<Integer> getPidsByPort(int port) {
        try {
            List<String> inputs = exec(getPidsByPortCmd + port);
            List<Integer> pids = parsePids(inputs);
            return pids;
        } catch (Exception e) {
            throw new RuntimeException("获取pid失败：" + port, e);
        }
    }

    @Override
    protected List<Integer> parsePids(List<String> inputs) {
        // COMMAND   PID USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
        // java    31676 root    4u  IPv4 2402128389      0t0  TCP *:avt-profile-2 (LISTEN)
        if (CollectionUtils.isEmpty(inputs)) {
            return null;
        }
        List<Integer> pids = new ArrayList<>();
        inputs.forEach(input -> {
            if (!input.contains("PID")) {
                String[] split = input.trim().split("\\s+");
                pids.add(Integer.parseInt(split[1]));
            }
        });
        return  pids;
    }

    @Override
    protected String getCmd(String cmd) {
        return cmdPrefix + cmd;
    }

    @Override
    protected String getStartCmd(String serverPath) {
        String startCmd;
        serverPath = Utils.isNullOrEmpty(serverPath) ? Utils.getBasePath() : serverPath;
        if (FileServiceImp.isEqual(serverPath, Utils.getBasePath())) {
            startCmd = FileServiceImp.combinePath(serverPath, START_CMD);
            if (!new File(startCmd).exists()) {
                startCmd = FileServiceImp.combinePath(serverPath, START_CMD_OLD);
            }
            if (!new File(startCmd).exists()) {
                File[] files = new File(serverPath).listFiles((dir, name) -> name.endsWith(SCRIPT_SUFFIX));
                if (files != null && files.length > 0) {
                    startCmd = files[0].getPath();
                }
            }
            if (!new File(startCmd).exists()) {
                throw new RuntimeException("无法找到正确的启动脚本：" + serverPath);
            }
        } else {
            startCmd = FileServiceImp.combinePath(serverPath, START_CMD_DEBUGGER);
        }
        return getCmd(startCmd);
    }

    @Override
    public boolean checkPath(String path) {
        if (path.contains(":")) {
            return false;
        }
        return true;
    }

    @Override
    protected List<SimpleProcess> getJavaProcesses() {
        List<SimpleProcess> processes = new ArrayList<>();
        List<String> javaProcesses = exec(getJavaProcessesCmd);
        if (!Utils.isNullOrEmpty(javaProcesses)) {
            javaProcesses.forEach(line-> {
                String[] array = line.split("\\s+");
                int pid = Integer.parseInt(array[1].replace("\"", ""));
                if (pid != 0) {
                    processes.add(new SimpleProcess(pid, "java"));
                }
            });
        }
        return processes;
    }
}
